package com.itany.corejava.code16_反射;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 石小俊
 * @date 2023年06月02日 9:35
 */
public class EmpFactoryMap {

    private static Map<String, String> map;

    static {
        map = new HashMap<>();
        try {
            // 通过IO读取文件内容,实现按行读取文件中数据的功能
            // 每一行表示一个key-value的键值对,其数据通过等号分割
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(
                            EmpFactoryMap
                                    .class
                                    .getClassLoader()
                                    .getResourceAsStream("emp.properties")));
            String line = null;
            while ((line = br.readLine()) != null) {
                // 开发中,配置文件中可能存在空行
                // 对于空行,不进行处理,直接读取下一行即可
                // 当line的值为空时,表示空行
                if (!"".equals(line)) {
                    // 此时读取了一行数据,其值为line,此时的值中间存在等号
                    // 需要通过等号进行分割,左边为key,右边为value
                    String[] arr = line.split("=");
                    map.put(arr[0], arr[1]);
                }
            }
        } catch (Exception e) {
            throw new ExceptionInInitializerError("加载配置文件出错");
        }
    }

    public static Emp getEmp() throws EmpCreateFailException {
        try {
            // 当解析完成emp.properties文件,其文件中的数据存储到Properties集合中
            // 通过反射,创建Emp对象
            // 获取Emp的Class对象
            Class<Emp> c = Emp.class;
            // 通过Class获取对应类的无参构造方法创建对象
            Emp emp = c.newInstance();

            // 获取Emp对象中所有的属性
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                // 在每个属性上,都是通过@Value注解为指定属性赋值
                // 获取对应属性的Value注解
                Value annotation = field.getAnnotation(Value.class);
                // 该注解通过value属性为指定的属性赋值
                // 先获取到value属性的值
                // 对应属性的值是根据value属性的值去配置文件中获取与之对应的数据
                // 此时配置文件中的数据已经进行解析过了,此时存放在Properties集合中
                // 简单来讲,此时的@Value注解中value属性的值是Properties集合中数据的key
                // 对应属性具体的值,是该key所对应的value
                // key:value属性的值
                String key = annotation.value();
                // value:根据key去Properties集合中获取对应的值
                String value = map.get(key);
                // 将value赋值给对应的属性
                // 此时所有属性均通过private进行封装了
                // 因此,需要取消权限控制检查
                field.setAccessible(true);
                // 为属性赋值
                field.set(emp, value);
            }
            return emp;
        } catch (InstantiationException e) {
            throw new EmpCreateFailException("Emp对象创建失败");
        } catch (IllegalAccessException e) {
            throw new EmpCreateFailException("Emp对象创建失败");
        }
    }
}
